package main

import (
	"encoding/json"
	"fmt"

	"log"
	"strconv"

	"database/sql"

	"go.etcd.io/bbolt"
	_ "modernc.org/sqlite"
)

// DeviceData represents a row in the device_data table
type DeviceData struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
	Data string `json:"data"`
}

// ReportData represents a row in the report_data table
type ReportData struct {
	ID          int    `json:"id"`
	ServiceName string `json:"service_name"`
	DeviceName  string `json:"device_name"`
	Data        string `json:"data"`
	ReportFlag  bool   `json:"report_flag"`
}

func sql2bblot() {
	// 打开 SQLite 数据库
	sqliteDB, err := sql.Open("sqlite", "openGW.db")
	if err != nil {
		log.Fatal(err)
	}
	defer sqliteDB.Close()

	// 打开 bbolt 数据库
	boltDB, err := bbolt.Open("openGW_bbolt.db", 0755, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer boltDB.Close()

	// 在单个事务中同时迁移 device_data 和 report_data 两个表的数据
	err = boltDB.Update(func(tx *bbolt.Tx) error {
		// 创建 buckets
		deviceBucket, err := tx.CreateBucketIfNotExists([]byte("device_data"))
		if err != nil {
			return err
		}

		reportBucket, err := tx.CreateBucketIfNotExists([]byte("report_data"))
		if err != nil {
			return err
		}

		// 迁移 device_data 表的数据
		if err := migrateDeviceData(sqliteDB, deviceBucket); err != nil {
			return err
		}

		// 迁移 report_data 表的数据
		if err := migrateReportData(sqliteDB, reportBucket); err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

	log.Println("数据成功从 SQLite 的 device_data 和 report_data 表导入到 bbolt!")
}

// migrateDeviceData 迁移 device_data 表数据
func migrateDeviceData(sqliteDB *sql.DB, bucket *bbolt.Bucket) error {
	// 从 SQLite 中读取 device_data 表的数据
	rows, err := sqliteDB.Query("SELECT id, name, data FROM device_data")
	if err != nil {
		return err
	}
	defer rows.Close()

	// 遍历 SQLite 数据库中的每一行
	for rows.Next() {
		var device DeviceData
		if err := rows.Scan(&device.ID, &device.Name, &device.Data); err != nil {
			return err
		}

		// 将设备数据转换为 JSON 格式
		deviceData, err := json.Marshal(device)
		if err != nil {
			return err
		}

		// 使用 ID 作为键，将数据存储到 bucket 中
		key := strconv.Itoa(device.ID)
		if err := bucket.Put([]byte(key), deviceData); err != nil {
			return err
		}
	}

	return nil
}

// migrateReportData 迁移 report_data 表数据
func migrateReportData(sqliteDB *sql.DB, bucket *bbolt.Bucket) error {
	// 从 SQLite 中读取 report_data 表的数据
	rows, err := sqliteDB.Query("SELECT id, service_name, device_name, data, report_flag FROM report_data")
	if err != nil {
		return err
	}
	defer rows.Close()

	// 遍历 SQLite 数据库中的每一行
	for rows.Next() {
		var report ReportData
		if err := rows.Scan(&report.ID, &report.ServiceName, &report.DeviceName, &report.Data, &report.ReportFlag); err != nil {
			return err
		}

		// 将报告数据转换为 JSON 格式
		reportData, err := json.Marshal(report)
		if err != nil {
			return err
		}

		// 使用 ID 作为键，将数据存储到 bucket 中
		key := strconv.Itoa(report.ID)
		if err := bucket.Put([]byte(key), reportData); err != nil {
			return err
		}
	}

	return nil
}

func main() {
	//sqlite 迁移
	//sql2bblot()

	db, err := bbolt.Open("./openGW_bbolt.db", 0666, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 打印当前数据
	if err := printData(db); err != nil {
		log.Fatal(err)
	}

	// 增加数据示例
	if err := addDeviceData(db, 1, "DeviceA", "DataA"); err != nil {
		log.Fatal(err)
	}
	if err := addReportData(db, 1, "ServiceA", "DeviceA", "ReportDataA", true); err != nil {
		log.Fatal(err)
	}

	// 打印更新后的数据
	if err := printData(db); err != nil {
		log.Fatal(err)
	}

	// // 删除数据示例
	// if err := deleteDeviceData(db, 1); err != nil {
	//     log.Fatal(err)
	// }
	// if err := deleteReportData(db, 1); err != nil {
	//     log.Fatal(err)
	// }

	// // 打印删除后的数据
	// if err := printData(db); err != nil {
	//     log.Fatal(err)
	// }
}

func printData(db *bbolt.DB) error {
	return db.View(func(tx *bbolt.Tx) error {
		// 打印 device_data 桶中的数据
		deviceBucket := tx.Bucket([]byte("device_data"))
		if deviceBucket != nil {
			log.Println("Device Data:")
			return deviceBucket.ForEach(func(k, v []byte) error {
				log.Printf("Key: %s, Value: %s\n", k, v)
				return nil
			})
		}

		// 打印 report_data 桶中的数据
		reportBucket := tx.Bucket([]byte("report_data"))
		if reportBucket != nil {
			log.Println("Report Data:")
			return reportBucket.ForEach(func(k, v []byte) error {
				log.Printf("Key: %s, Value: %s\n", k, v)
				return nil
			})
		}

		return nil
	})
}

func addDeviceData(db *bbolt.DB, id int, name, data string) error {
	return db.Update(func(tx *bbolt.Tx) error {
		bucket := tx.Bucket([]byte("device_data"))
		if bucket == nil {
			return fmt.Errorf("Bucket not found")
		}

		device := DeviceData{ID: id, Name: name, Data: data}
		deviceData, err := json.Marshal(device)
		if err != nil {
			return err
		}

		key := strconv.Itoa(id)
		return bucket.Put([]byte(key), deviceData)
	})
}

func addReportData(db *bbolt.DB, id int, serviceName, deviceName, data string, reportFlag bool) error {
	return db.Update(func(tx *bbolt.Tx) error {
		bucket := tx.Bucket([]byte("report_data"))
		if bucket == nil {
			return fmt.Errorf("添加失败")
		}

		report := ReportData{ID: id, ServiceName: serviceName, DeviceName: deviceName, Data: data, ReportFlag: reportFlag}
		reportData, err := json.Marshal(report)
		if err != nil {
			return err
		}

		key := strconv.Itoa(id)
		return bucket.Put([]byte(key), reportData)
	})
}

func deleteDeviceData(db *bbolt.DB, id int) error {
	return db.Update(func(tx *bbolt.Tx) error {
		bucket := tx.Bucket([]byte("device_data"))
		if bucket == nil {
			return fmt.Errorf("Bucket not found")
		}

		key := strconv.Itoa(id)
		return bucket.Delete([]byte(key))
	})
}

func deleteReportData(db *bbolt.DB, id int) error {
	return db.Update(func(tx *bbolt.Tx) error {
		bucket := tx.Bucket([]byte("report_data"))
		if bucket == nil {
			return fmt.Errorf("Bucket not found")
		}

		key := strconv.Itoa(id)
		return bucket.Delete([]byte(key))
	})
}
